#include <XanaduCore/XString.h>
#include <XanaduCore/XRuntime.h>
#include <XanaduCore/XBase64.h>


// constructor
XString::XString() noexcept
{
	this->_memory_malloc(0);
}

// constructor
XString::XString(size_type _Count, const _Elem _Char) noexcept
{
	this->_memory_malloc(_Count);
	if(this->_string_data && this->_string_length == _Count)
	{
		Xanadu::memset(this->_string_data, _Char, this->_string_length);
	}
}

// constructor
XString::XString(const _Elem* _String) noexcept
{
	auto		vLength = Xanadu::strlen(_String);
	this->_memory_malloc(vLength);
	if(this->_string_data && this->_string_length == vLength)
	{
		Xanadu::memcpy(this->_string_data, _String, vLength);
	}
}

// constructor
XString::XString(const _Elem* _String, size_type _Length) noexcept
{
	this->_memory_malloc(_Length);
	if(this->_string_data && this->_string_length == _Length)
	{
		Xanadu::memcpy(this->_string_data, _String, _Length);
	}
}

// constructor
XString::XString(const std::string& _String) noexcept
{
	auto		vLength = _String.length();
	this->_memory_malloc(vLength);
	if(this->_string_data && this->_string_length == vLength)
	{
		Xanadu::memcpy(this->_string_data, _String.data(), vLength);
	}
}

// constructor
XString::XString(const std::string& _String, size_type _Count) noexcept
{
	auto		vLength = _Count;
	this->_memory_malloc(vLength);
	if(this->_string_data && this->_string_length == vLength)
	{
		Xanadu::memcpy(this->_string_data, _String.data(), vLength);
	}
}

// constructor
XString::XString(const XByteArray& _Bytes) noexcept
{
	auto		vLength = _Bytes.length();
	this->_memory_malloc(vLength);
	if(this->_string_data && this->_string_length == vLength)
	{
		Xanadu::memcpy(this->_string_data, _Bytes.data(), vLength);
	}
}

// constructor
XString::XString(const XByteArray& _Bytes, size_type _Count) noexcept
{
	auto		vLength = _Count;
	this->_memory_malloc(vLength);
	if(this->_string_data && this->_string_length == vLength)
	{
		Xanadu::memcpy(this->_string_data, _Bytes.data(), vLength);
	}
}

// constructor
XString::XString(const XString& _String) noexcept
{
	auto		vLength = _String.length();
	this->_memory_malloc(vLength);
	if(this->_string_data && this->_string_length == vLength)
	{
		Xanadu::memcpy(this->_string_data, _String.data(), vLength);
	}
}

// constructor
XString::XString(const XString& _String, size_type _Count) noexcept
{
	auto		vLength = _Count;
	this->_memory_malloc(vLength);
	if(this->_string_data && this->_string_length == vLength)
	{
		Xanadu::memcpy(this->_string_data, _String.data(), vLength);
	}
}

// constructor
XString::XString(XString&& _String) noexcept
{
	if(this->_string_data != _String._string_data)
	{
		this->_memory_free();
		this->_string_data = _String._string_data;
		this->_string_length = _String._string_length;
		this->_string_capacity = _String._string_capacity;
		_String._string_data = nullptr;
		_String._string_length = 0;
		_String._string_capacity = 0;
		_String._memory_malloc(0);
	}
}

// destructor
XString::~XString() noexcept
{
	this->_memory_free();
}



// memory: Computing demand space
XString::size_type XString::_memory_calculation_capacity(size_type _Length) const noexcept
{
	size_type	vCapacity = 32;
	while(_Length >= vCapacity)
	{
		vCapacity <<= 1;
	};
	return vCapacity;
}

// memory: malloc
bool XString::_memory_malloc(size_type _Length) noexcept
{
	auto		vTempCapacity = _memory_calculation_capacity(_Length);
	auto		vTempData = new(std::nothrow) _Elem [vTempCapacity];
	if(vTempData)
	{
		Xanadu::memset(vTempData, 0, vTempCapacity);
		this->_memory_free();
		this->_string_data = vTempData;
		this->_string_length = _Length;
		this->_string_capacity = vTempCapacity;
		return true;
	}
	return false;
}

// memory: resize
bool XString::_memory_resize(size_type _Length) noexcept
{
	if(_Length == this->_string_length)
	{
		return true;
	}
	else
	{
		auto		vTempCapacity = _memory_calculation_capacity(_Length);
		auto		vTempData = new(std::nothrow) _Elem [vTempCapacity];
		if(vTempData)
		{
			Xanadu::memset(vTempData, 0, vTempCapacity);
			Xanadu::memmove(vTempData, this->_string_data, _Length < this->_string_length ? _Length : this->_string_length);
			this->_memory_free();
			this->_string_data = vTempData;
			this->_string_length = _Length;
			this->_string_capacity = vTempCapacity;
			return true;
		}
		return false;
	}
}

// memory: surplus
XString::size_type XString::_memory_surplus() const noexcept
{
	return this->_string_capacity - this->_string_length;
}

// memory: free
void XString::_memory_free() noexcept
{
	if(this->_string_data)
	{
		delete[] this->_string_data;
		this->_string_data = nullptr;
	}
	this->_string_length = 0;
	this->_string_capacity = 0;
}



// fix: pos
XString::size_type XString::_fix_pos(size_type _Pos) const noexcept
{
	if(_Pos == XString::npos)
	{
		return 0;
	}
	else if(_Pos >= this->_string_length)
	{
		return this->_string_length - 1;
	}
	return _Pos;
}

// fix: length
XString::size_type XString::_fix_length(const _Elem* _String, size_type _Length) const noexcept
{
	if(_Length == XString::npos)
	{
		_Length = Xanadu::strlen(_String);
	}
	return _Length;
}



// private: contains
bool XString::_contains(const _Elem* _String, size_type _Length, Xanadu::CaseSensitivity _XCS) const noexcept
{
	_Length = this->_fix_length(_String, _Length);
	if(_String && _Length > 0)
	{
		if(_XCS == Xanadu::CaseInsensitive)
		{
			auto		vSourceUpper = this->toUpper();
			auto		vSubstrUpper = XString(_String, _Length).toUpper();
			auto		vFind = Xanadu::strstr(vSourceUpper._string_data, vSubstrUpper._string_data);
			return vFind;
		}
		else
		{
			auto		vFind = Xanadu::strstr(this->_string_data, _String);
			return vFind;
		}
	}
	return false;
}

// private: compare
int XString::_compare(const _Elem* _String, size_type _Length, Xanadu::CaseSensitivity _XCS) const noexcept
{
	_Length = this->_fix_length(_String, _Length);
	if(_String && _Length > 0)
	{
		if(_XCS == Xanadu::CaseInsensitive)
		{
			auto		vSourceUpper = this->toUpper();
			auto		vSubstrUpper = XString(_String, _Length).toUpper();
			auto		vFind = Xanadu::strcmp(vSourceUpper._string_data, vSubstrUpper._string_data);
			return vFind;
		}
		else
		{
			auto		vFind = Xanadu::strcmp(this->_string_data, _String);
			return vFind;
		}
	}
	return Xanadu::strcmp(nullptr, _String);
}

// private: find
XString::size_type XString::_find(const _Elem* _String, size_type _Length, size_type _Pos, Xanadu::CaseSensitivity _XCS) const noexcept
{
	_Length = this->_fix_length(_String, _Length);
	if(_String && _Length > 0 && this->_string_length > 0)
	{
		if(_Pos >= this->_string_length)
		{
			return XString::npos;
		}
		else
		{
			if(_XCS == Xanadu::CaseInsensitive)
			{
				auto		vSourceUpper = this->toUpper();
				auto		vSubstrUpper = XString(_String, _Length).toUpper();
				auto		vFind = Xanadu::strstr(vSourceUpper._string_data + _Pos, vSubstrUpper._string_data);
				if(vFind)
				{
					return vFind - vSourceUpper._string_data;
				}
			}
			else
			{
				auto		vFind = Xanadu::strstr(this->_string_data + _Pos, _String);
				if(vFind)
				{
					return vFind - this->_string_data;
				}
			}
		}
	}
	return XString::npos;
}

// private: rfind
XString::size_type XString::_rfind(const _Elem* _String, size_type _Length, size_type _Pos, Xanadu::CaseSensitivity _XCS) const noexcept
{
	_Length = this->_fix_length(_String, _Length);
	if(_String && _Length > 0 && this->_string_length > 0)
	{
		if(_Length <= this->_string_length && _Pos < this->_string_length)
		{
			if(_XCS == Xanadu::CaseInsensitive)
			{
				auto		vSourceUpper = this->toUpper();
				auto		vSubstrUpper = XString(_String, _Length).toUpper();
				for(auto vIndex = _Pos; vIndex != XString::npos; --vIndex)
				{
					if(Xanadu::strncmp(vSourceUpper._string_data + vIndex, vSubstrUpper._string_data, _Length) == 0)
					{
						return vIndex;
					}
				}
			}
			else
			{
				for(auto vIndex = _Pos; vIndex != XString::npos; --vIndex)
				{
					if(Xanadu::strncmp(this->_string_data + vIndex, _String, _Length) == 0)
					{
						return vIndex;
					}
				}
			}
		}
	}
	return XString::npos;
}

// private: prepend
void XString::_prepend(const _Elem* _String, size_type _Length) noexcept
{
	_Length = this->_fix_length(_String, _Length);
	if(_String && _Length > 0)
	{
		if(this->_memory_surplus() > _Length)
		{
			Xanadu::memmove(this->_string_data + _Length, this->_string_data, this->_string_length);
			Xanadu::memcpy(this->_string_data, _String, _Length);
			this->_string_length += _Length;
		}
		else
		{
			auto		vTempLength = _Length + this->_string_length;
			auto		vTempCapacity = this->_memory_calculation_capacity(vTempLength);
			auto		vTempData = new(std::nothrow) _Elem [vTempCapacity];
			if(vTempData)
			{
				Xanadu::memset(vTempData, 0, vTempCapacity);
				Xanadu::memcpy(vTempData, _String, _Length);
				Xanadu::memcpy(vTempData + _Length, this->_string_data, this->_string_length);

				this->_memory_free();
				this->_string_data = vTempData;
				this->_string_length = vTempLength;
				this->_string_capacity = vTempCapacity;
			}
		}
	}
}

// private: insert
void XString::_insert(size_type _Pos, const _Elem* _String, size_type _Length) noexcept
{
	_Pos = this->_fix_pos(_Pos);
	_Length = this->_fix_length(_String, _Length);
	if(_String && _Length > 0)
	{
		if(this->_memory_surplus() > _Length)
		{
			Xanadu::memmove(this->_string_data + _Pos + _Length, this->_string_data + _Pos, this->_string_length - _Pos);
			Xanadu::memcpy(this->_string_data + _Pos, _String, _Length);
			this->_string_length += _Length;
		}
		else
		{
			auto		vTempLength = _Length + this->_string_length;
			auto		vTempCapacity = this->_memory_calculation_capacity(vTempLength);
			auto		vTempData = new(std::nothrow) _Elem [vTempCapacity];
			if(vTempData)
			{
				Xanadu::memset(vTempData, 0, vTempCapacity);
				Xanadu::memcpy(vTempData, this->_string_data, _Pos);
				Xanadu::memcpy(vTempData + _Pos, _String, _Length);
				Xanadu::memcpy(vTempData + _Pos + _Length, this->_string_data + _Pos, this->_string_length - _Pos);

				this->_memory_free();
				this->_string_data = vTempData;
				this->_string_length = vTempLength;
				this->_string_capacity = vTempCapacity;
			}
		}
	}
}

// private: append
void XString::_append(const _Elem* _String, size_type _Length) noexcept
{
	_Length = this->_fix_length(_String, _Length);
	if(_String && _Length > 0)
	{
		if(this->_memory_surplus() > _Length)
		{
			Xanadu::memcpy(this->_string_data + this->_string_length, _String, _Length);
			this->_string_length += _Length;
		}
		else
		{
			auto		vTempLength = _Length + this->_string_length;
			auto		vTempCapacity = this->_memory_calculation_capacity(vTempLength);
			auto		vTempData = new(std::nothrow) _Elem [vTempCapacity];
			if(vTempData)
			{
				Xanadu::memset(vTempData, 0, vTempCapacity);
				Xanadu::memcpy(vTempData, this->_string_data, this->_string_length);
				Xanadu::memcpy(vTempData + this->_string_length, _String, _Length);

				this->_memory_free();
				this->_string_data = vTempData;
				this->_string_length = vTempLength;
				this->_string_capacity = vTempCapacity;
			}
		}
	}
}

// private: remove
void XString::_remove(size_type _Pos, size_type _Length) noexcept
{
	if(_Pos < this->_string_length)
	{
		if(_Length)
		{
			if(this->_string_length - _Pos < _Length)
			{
				_Length = this->_string_length - _Pos;
			}

			Xanadu::memmove(this->_string_data + _Pos, this->_string_data + _Pos + _Length, this->_string_length - _Pos - _Length);
			Xanadu::memset(this->_string_data + (this->_string_length - _Length), 0, _Length);
			this->_string_length -= _Length;
		}
	}
}

// private: remove
void XString::_remove(const _Elem* _String, size_type _Length, Xanadu::CaseSensitivity _XCS) noexcept
{
	size_type	vPos = 0;
	_Length = this->_fix_length(_String, _Length);
	do
	{
		vPos = this->_find(_String, _Length, vPos, _XCS);
		if(XString::npos != vPos)
		{
			this->_remove(vPos, _Length);
		}
	} while(XString::npos != vPos);
}

// private: replace
void XString::_replace(size_type _Pos, size_type _Length, const _Elem* _After, size_type _LengthA) noexcept
{
	_LengthA = this->_fix_length(_After, _LengthA);
	if(_Pos < this->_string_length && _LengthA > 0)
	{
		if(_LengthA == _Length)
		{
			Xanadu::memcpy(this->_string_data + _Pos, _After, _LengthA);
		}
		else if(_LengthA > _Length && this->_memory_surplus() <= (_LengthA - _Length))
		{
			auto		vTempLength = this->_string_length + _LengthA - _Length;
			auto		vTempCapacity = this->_memory_calculation_capacity(vTempLength);
			auto		vTempData = new(std::nothrow) _Elem [vTempCapacity];
			if(vTempData)
			{
				Xanadu::memset(vTempData, 0, vTempCapacity);
				Xanadu::memcpy(vTempData, this->_string_data, _Pos);
				Xanadu::memcpy(vTempData + _Pos, _After, _LengthA);
				Xanadu::memcpy(vTempData + _Pos + _LengthA, this->_string_data + _Pos + _Length, this->_string_length - _Pos - _Length);

				this->_memory_free();
				this->_string_data = vTempData;
				this->_string_length = vTempLength;
				this->_string_capacity = vTempCapacity;
			}
		}
		else
		{
			auto		vSurplus = this->_string_length - _Pos;
			auto		vAddress = this->_string_data + _Pos;
			Xanadu::memmove(vAddress + _LengthA, vAddress + _Length, vSurplus - _Length);
			Xanadu::memcpy(vAddress, _After, _LengthA);
			if(_Length > _LengthA)
			{
				Xanadu::memset(vAddress + vSurplus + _Length - _LengthA, 0, _Length - _LengthA);
			}
			this->_string_length += _LengthA;
			this->_string_length -= _Length;
		}
	}
}

// private: replace
void XString::_replace(const _Elem* _Before, size_type _LengthB, const _Elem* _After, size_type _LengthA, Xanadu::CaseSensitivity _XCS) noexcept
{
	size_type	vPos = 0;
	do
	{
		vPos = this->_find(_Before, _LengthB, vPos, _XCS);
		if(XString::npos != vPos)
		{
			this->_replace(vPos, _LengthB, _After, _LengthA);
			vPos += _LengthA;
		}
	} while(XString::npos != vPos);
}

// private: middle
XString XString::_middle(const _Elem* _Left, size_type _LengthL, const _Elem* _Right, size_type _LengthR, Xanadu::CaseSensitivity _XCS) const noexcept
{
	_LengthL = this->_fix_length(_Left, _LengthL);
	_LengthR = this->_fix_length(_Right, _LengthR);
	if(_Left == nullptr || _Right == nullptr || _LengthL == 0 || _LengthR == 0)
	{
		return {};
	}

	auto		vPosLeft = this->_find(_Left, _LengthL, 0, _XCS);
	if(XString::npos != vPosLeft)
	{
		vPosLeft += _LengthL;
		auto		vPosRight = this->_find(_Right, _LengthR, vPosLeft, _XCS);
		if(XString::npos != vPosRight)
		{
			return substr(vPosLeft, vPosRight - vPosLeft);
		}
	}
	return {};
}

// private: startsWith
bool XString::_startsWith(const _Elem* _String, size_type _Length, Xanadu::CaseSensitivity _XCS) const noexcept
{
	_Length = this->_fix_length(_String, _Length);
	if(this->_string_length >= _Length)
	{
		return this->left(_Length)._compare(_String, _Length, _XCS) == 0;
	}
	return false;
}

// private: endsWith
bool XString::_endsWith(const _Elem* _String, size_type _Length, Xanadu::CaseSensitivity _XCS) const noexcept
{
	_Length = this->_fix_length(_String, _Length);
	if(this->_string_length >= _Length)
	{
		return this->right(_Length)._compare(_String, _Length, _XCS) == 0;
	}
	return false;
}



// [opt] operators overload =
XString& XString::operator = (const _Elem* _String) noexcept
{
	this->_memory_free();
	if(_String == nullptr || Xanadu::strlen(_String) == 0)
	{
		this->_memory_malloc(0);
	}
	else
	{
		this->_append(_String, Xanadu::strlen(_String));
	}
	return *this;
}

// [opt] operators overload =
XString& XString::operator = (const std::string& _String) noexcept
{
	this->_memory_free();
	if(_String.empty())
	{
		this->_memory_malloc(0);
	}
	else
	{
		this->_append(_String.data(), _String.size());
	}
	return *this;
}

// [opt] operators overload =
XString& XString::operator = (const XByteArray& _Bytes) noexcept
{
	this->_memory_free();
	if(_Bytes.empty())
	{
		this->_memory_malloc(0);
	}
	else
	{
		this->_append(_Bytes.data(), _Bytes.size());
	}
	return *this;
}

// [opt] operators overload =
XString& XString::operator = (const XString& _String) noexcept
{
	if(this != &_String)
	{
		this->_memory_free();
		if(_String._string_length > 0)
		{
			this->_append(_String._string_data, _String._string_length);
		}
		else
		{
			this->_memory_malloc(0);
		}
	}
	return *this;
}

// [opt] operators overload =
XString& XString::operator = (XString&& _String) noexcept
{
	if(this->_string_data != _String._string_data)
	{
		this->_memory_free();
		this->_string_data = _String._string_data;
		this->_string_length = _String._string_length;
		this->_string_capacity = _String._string_capacity;
		_String._string_data = nullptr;
		_String._string_length = 0;
		_String._string_capacity = 0;
		_String._memory_malloc(0);
	}
	return *this;
}



// [opt] operators overload []
XString::_Elem& XString::operator [] (size_type _Index)
{
	if(_Index < this->size())
	{
		return this->_string_data[_Index];
	}
	throw std::exception(std::logic_error("Subscript out of bounds"));
}

// [opt] operators overload []
XString::_Elem XString::operator [] (size_type _Index) const
{
	if(_Index < this->size())
	{
		return this->_string_data[_Index];
	}
	throw std::exception(std::logic_error("Subscript out of bounds"));
}



// [opt] operators overload +=
XString& XString::operator += (_Elem _Char) noexcept
{
	_Elem		vBytes[2] = {_Char, '\0'};
	this->_append(vBytes, 1);
	return *this;
}

// [opt] operators overload +=
XString& XString::operator += (const _Elem* _String) noexcept
{
	this->_append(_String, Xanadu::strlen(_String));
	return *this;
}

// [opt] operators overload +=
XString& XString::operator += (const std::string& _String) noexcept
{
	this->_append(_String.data(), _String.size());
	return *this;
}

// [opt] operators overload +=
XString& XString::operator += (const XString& _String) noexcept
{
	this->_append(_String.data(), _String.size());
	return *this;
}



// [opt] operators overload +
XString XString::operator + (_Elem _Char) const noexcept
{
	auto		vTemp = *this;
	vTemp += _Char;
	return vTemp;
}

// [opt] operators overload +
XString XString::operator + (const _Elem* _String) const noexcept
{
	auto		vTemp = *this;
	vTemp += _String;
	return vTemp;
}

// [opt] operators overload +
XString XString::operator + (const std::string& _String) const noexcept
{
	auto		vTemp = *this;
	vTemp += _String;
	return vTemp;
}

// [opt] operators overload +
XString XString::operator + (const XString& _String) const noexcept
{
	auto		vTemp = *this;
	vTemp += _String;
	return vTemp;
}



// [opt] operators overload ==
bool XString::operator == (_Elem _Char) const noexcept
{
	_Elem		vBytes[2] = {_Char, '\0'};
	return this->_compare(vBytes, 1, Xanadu::CaseSensitive) == 0;
}

// [opt] operators overload ==
bool XString::operator == (const _Elem* _String) const noexcept
{
	return this->_compare(_String, Xanadu::strlen(_String), Xanadu::CaseSensitive) == 0;
}

// [opt] operators overload ==
bool XString::operator == (const XString& _String) const noexcept
{
	return this->_compare(_String._string_data, _String._string_length, Xanadu::CaseSensitive) == 0;
}

// [opt] operators overload !=
bool XString::operator != (_Elem _Char) const noexcept
{
	_Elem		vBytes[2] = {_Char, '\0'};
	return this->_compare(vBytes, 1, Xanadu::CaseSensitive) != 0;
}

// [opt] operators overload !=
bool XString::operator != (const _Elem* _String) const noexcept
{
	return this->_compare(_String, Xanadu::strlen(_String), Xanadu::CaseSensitive) != 0;
}

// [opt] operators overload !=
bool XString::operator != (const XString& _String) const noexcept
{
	return this->_compare(_String._string_data, _String._string_length, Xanadu::CaseSensitive) != 0;
}

// [opt] operators overload <
bool XString::operator < (_Elem _Char) const noexcept
{
	_Elem		vBytes[2] = {_Char, '\0'};
	return this->_compare(vBytes, 1, Xanadu::CaseSensitive) < 0;
}

// [opt] operators overload <
bool XString::operator < (const _Elem* _String) const noexcept
{
	return this->_compare(_String, Xanadu::strlen(_String), Xanadu::CaseSensitive) < 0;
}

// [opt] operators overload <
bool XString::operator < (const XString& _String) const noexcept
{
	return this->_compare(_String._string_data, _String._string_length, Xanadu::CaseSensitive) < 0;
}

// [opt] operators overload >
bool XString::operator > (_Elem _Char) const noexcept
{
	_Elem		vBytes[2] = {_Char, '\0'};
	return this->_compare(vBytes, 1, Xanadu::CaseSensitive) > 0;
}

// [opt] operators overload >
bool XString::operator > (const _Elem* _String) const noexcept
{
	return this->_compare(_String, Xanadu::strlen(_String), Xanadu::CaseSensitive) > 0;
}

// [opt] operators overload >
bool XString::operator > (const XString& _String) const noexcept
{
	return this->_compare(_String._string_data, _String._string_length, Xanadu::CaseSensitive) > 0;
}

// [opt] operators overload <=
bool XString::operator <= (_Elem _Char) const noexcept
{
	_Elem		vBytes[2] = {_Char, '\0'};
	return this->_compare(vBytes, 1, Xanadu::CaseSensitive) <= 0;
}

// [opt] operators overload <=
bool XString::operator <= (const _Elem* _String) const noexcept
{
	return this->_compare(_String, Xanadu::strlen(_String), Xanadu::CaseSensitive) <= 0;
}

// [opt] operators overload <=
bool XString::operator <= (const XString& _String) const noexcept
{
	return this->_compare(_String._string_data, _String._string_length, Xanadu::CaseSensitive) <= 0;
}

// [opt] operators overload >=
bool XString::operator >= (_Elem _Char) const noexcept
{
	_Elem		vBytes[2] = {_Char, '\0'};
	return this->_compare(vBytes, 1, Xanadu::CaseSensitive) >= 0;
}

// [opt] operators overload >=
bool XString::operator >= (const _Elem* _String) const noexcept
{
	return this->_compare(_String, Xanadu::strlen(_String), Xanadu::CaseSensitive) >= 0;
}

// [opt] operators overload >=
bool XString::operator >= (const XString& _String) const noexcept
{
	return this->_compare(_String._string_data, _String._string_length, Xanadu::CaseSensitive) >= 0;
}



// [get] Is there a string
bool XString::exist() const noexcept
{
	return this->_string_data && this->_string_length;
}

// [get] Is there a string
bool XString::empty() const noexcept
{
	return this->_string_data == nullptr || this->_string_length == 0;
}

// [get] a C compatible string ending with '\0'
XString::_Elem* XString::data() noexcept
{
	return this->_string_data;
}

// [get] a C compatible string ending with '\0'
const XString::_Elem* XString::data() const noexcept
{
	return this->_string_data;
}

// [get] length of string
XString::size_type XString::size() const noexcept
{
	return this->_string_length;
}

// [get] length of string
XString::size_type XString::length() const noexcept
{
	return this->_string_length;
}

// [get] capacity of string
XString::size_type XString::capacity() const noexcept
{
	return this->_string_capacity;
}



// Empty all spaces with 0
void XString::clear() noexcept
{
	this->_memory_free();
	this->_memory_malloc(0);
}

// Exchange string
void XString::swap(XString& _String) noexcept
{
	if(this->_string_data != _String._string_data)
	{
		auto		vTempData = this->_string_data;
		auto		vTempLength = this->_string_length;
		auto		vTempCapacity = this->_string_capacity;

		this->_string_data = _String._string_data;
		this->_string_length = _String._string_length;
		this->_string_capacity = _String._string_capacity;
		_String._string_data = vTempData;
		_String._string_length = vTempLength;
		_String._string_capacity = vTempCapacity;
	}
}

// Gets the maximum length allowed
XString::size_type XString::max_size() const noexcept
{
	return 0xFFFFFFFFULL;
}

// Resizing
void XString::resize(size_type _Length) noexcept
{
	this->_memory_resize(_Length);
}

// Resizing
void XString::resize(size_type _Length, _Elem _Char) noexcept
{
	this->_memory_resize(_Length);
	for(auto vIndex = 0U; vIndex < this->_string_length && this->_string_data; ++vIndex)
	{
		operator[](vIndex) = _Char;
	}
}

// Truncates the subscript POS of the byte array. If POS goes beyond the end of the array, nothing happens.
void XString::truncate(size_type _Index) noexcept
{
	if (_Index < this->size())
	{
		this->resize(_Index);
	}
}

// Returns a string that has whitespace removed from the start and the end, and that has each sequence of internal whitespace replaced with a single space.
XString XString::simplified() const noexcept
{
	auto		vString = XString();
	auto		vNumber = 0;
	auto		vBegin = true;
	for(auto vIndex = 0ULL; vIndex < this->size(); ++vIndex)
	{
		if(XString::isSpace(this->data()[vIndex]))
		{
			++vNumber;
		}
		else
		{
			if(!vBegin)
			{
				if(vNumber)
				{
					vString.append(' ');
				}
			}
			vString.append(data()[vIndex]);

			vNumber = 0;
			vBegin = false;
		}
	}
	return vString;
}



// Extracting substrings from strings
XString XString::substr(size_type _Pos) const noexcept
{
	return this->substr(_Pos, XString::npos);
}

// Extracting substrings from strings
XString XString::substr(size_type _Pos, size_type _Length) const noexcept
{
	if(_Pos < this->size())
	{
		if(_Length == XString::npos)
		{
			return {this->data() + _Pos, this->size() - _Pos};
		}
		else
		{
			return {this->data() + _Pos, this->size() - _Pos > _Length ? _Length : this->size() - _Pos};
		}
	}
	else
	{
		return {};
	}
}

// Gets the substring to the left of the source string
XString XString::left(size_type _Pos) const noexcept
{
	return this->substr(0, _Pos);
}

// Gets the substring to the right of the source string
XString XString::right(size_type _Pos) const noexcept
{
	return this->substr(this->size() - _Pos, XString::npos);
}



// [mid] Gets the substring in the middle of the source string
XString XString::mid(size_type _Pos) const noexcept
{
	return this->mid(_Pos, XString::npos);
}

// [mid] Gets the substring in the middle of the source string
XString XString::mid(size_type _Pos, size_type _Size) const noexcept
{
	return this->substr(_Pos, _Size);
}

// [mid] Gets the substring in the middle of the source string
XString XString::mid(const _Elem* _Left, const _Elem* _Right) const noexcept
{
	return this->_middle(_Left, Xanadu::strlen(_Left), _Right, Xanadu::strlen(_Right), Xanadu::CaseSensitive);
}

// [mid] Gets the substring in the middle of the source string
XString XString::mid(const _Elem* _Left, const _Elem* _Right, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_middle(_Left, Xanadu::strlen(_Left), _Right, Xanadu::strlen(_Right), _XCS);
}

// [mid] Gets the substring in the middle of the source string
XString XString::mid(const _Elem* _Left, const XString& _Right) const noexcept
{
	return this->_middle(_Left, Xanadu::strlen(_Left), _Right.data(), _Right.size(), Xanadu::CaseSensitive);
}

// [mid] Gets the substring in the middle of the source string
XString XString::mid(const _Elem* _Left, const XString& _Right, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_middle(_Left, Xanadu::strlen(_Left), _Right.data(), _Right.size(), _XCS);
}

// [mid] Gets the substring in the middle of the source string
XString XString::mid(const XString& _Left, const _Elem* _Right) const noexcept
{
	return this->_middle(_Left.data(), _Left.size(), _Right, Xanadu::strlen(_Right), Xanadu::CaseSensitive);
}

// [mid] Gets the substring in the middle of the source string
XString XString::mid(const XString& _Left, const _Elem* _Right, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_middle(_Left.data(), _Left.size(), _Right, Xanadu::strlen(_Right), _XCS);
}

// [mid] Gets the substring in the middle of the source string
XString XString::mid(const XString& _Left, const XString& _Right) const noexcept
{
	return this->_middle(_Left.data(), _Left.size(), _Right.data(), _Right.size(), Xanadu::CaseSensitive);
}

// [mid] Gets the substring in the middle of the source string
XString XString::mid(const XString& _Left, const XString& _Right, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_middle(_Left.data(), _Left.size(), _Right.data(), _Right.size(), _XCS);
}



// Detects whether the string starts with the specified prefix
bool XString::startsWith(_Elem _Char) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->_startsWith(vBytes, 1, Xanadu::CaseSensitive);
}

// Detects whether the string starts with the specified prefix
bool XString::startsWith(_Elem _Char, Xanadu::CaseSensitivity _XCS) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->_startsWith(vBytes, 1, _XCS);
}

// Detects whether the string starts with the specified prefix
bool XString::startsWith(const _Elem* _Memory) const noexcept
{
	return this->_startsWith(_Memory, Xanadu::strlen(_Memory), Xanadu::CaseSensitive);
}

// Detects whether the string starts with the specified prefix
bool XString::startsWith(const _Elem* _Memory, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_startsWith(_Memory, Xanadu::strlen(_Memory), _XCS);
}

// Detects whether the string starts with the specified prefix
bool XString::startsWith(const _Elem* _Memory, size_type _Length) const noexcept
{
	return this->_startsWith(_Memory, _Length, Xanadu::CaseSensitive);
}

// Detects whether the string starts with the specified prefix
bool XString::startsWith(const _Elem* _Memory, size_type _Length, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_startsWith(_Memory, _Length, _XCS);
}

// Detects whether the string starts with the specified prefix
bool XString::startsWith(const XString& _String) const noexcept
{
	return this->_startsWith(_String.data(), _String.size(), Xanadu::CaseSensitive);
}

// Detects whether the string starts with the specified prefix
bool XString::startsWith(const XString& _String, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_startsWith(_String.data(), _String.size(), _XCS);
}



// Detects whether the string ends with the specified suffix
bool XString::endsWith(_Elem _Char) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->_endsWith(vBytes, 1, Xanadu::CaseSensitive);
}

// Detects whether the string ends with the specified suffix
bool XString::endsWith(_Elem _Char, Xanadu::CaseSensitivity _XCS) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->_endsWith(vBytes, 1, _XCS);
}

// Detects whether the string ends with the specified suffix
bool XString::endsWith(const _Elem* _Memory) const noexcept
{
	return this->_endsWith(_Memory, Xanadu::strlen(_Memory), Xanadu::CaseSensitive);
}

// Detects whether the string ends with the specified suffix
bool XString::endsWith(const _Elem* _Memory, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_endsWith(_Memory, Xanadu::strlen(_Memory), _XCS);
}

// Detects whether the string ends with the specified suffix
bool XString::endsWith(const _Elem* _Memory, size_type _Length) const noexcept
{
	return this->_endsWith(_Memory, _Length, Xanadu::CaseSensitive);
}

// Detects whether the string ends with the specified suffix
bool XString::endsWith(const _Elem* _Memory, size_type _Length, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_endsWith(_Memory, _Length, _XCS);
}

// Detects whether the string ends with the specified suffix
bool XString::endsWith(const XString& _String) const noexcept
{
	return this->_endsWith(_String.data(), _String.size(), Xanadu::CaseSensitive);
}

// Detects whether the string ends with the specified suffix
bool XString::endsWith(const XString& _String, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_endsWith(_String.data(), _String.size(), _XCS);
}



// Find in positive order from the specified location
XString::size_type XString::find(_Elem _Char) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->_find(vBytes, 1, 0, Xanadu::CaseSensitive);
}

// Find in positive order from the specified location
XString::size_type XString::find(_Elem _Char, Xanadu::CaseSensitivity _XCS) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->_find(vBytes, 1, 0, _XCS);
}

// Find in positive order from the specified location
XString::size_type XString::find(_Elem _Char, size_type _Pos) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->_find(vBytes, 1, _Pos, Xanadu::CaseSensitive);
}

// Find in positive order from the specified location
XString::size_type XString::find(_Elem _Char, size_type _Pos, Xanadu::CaseSensitivity _XCS) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->_find(vBytes, 1, _Pos, _XCS);
}

// Find in positive order from the specified location
XString::size_type XString::find(const _Elem* _String) const noexcept
{
	return this->_find(_String, Xanadu::strlen(_String), 0, Xanadu::CaseSensitive);
}

// Find in positive order from the specified location
XString::size_type XString::find(const _Elem* _String, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_find(_String, Xanadu::strlen(_String), 0, _XCS);
}

// Find in positive order from the specified location
XString::size_type XString::find(const _Elem* _String, size_type _Pos) const noexcept
{
	return this->_find(_String, Xanadu::strlen(_String), _Pos, Xanadu::CaseSensitive);
}

// Find in positive order from the specified location
XString::size_type XString::find(const _Elem* _String, size_type _Pos, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_find(_String, Xanadu::strlen(_String), _Pos, _XCS);
}

// Find in positive order from the specified location
XString::size_type XString::find(const _Elem* _String, size_type _Length, size_type _Pos) const noexcept
{
	return this->_find(_String, _Length, _Pos, Xanadu::CaseSensitive);
}

// Find in positive order from the specified location
XString::size_type XString::find(const _Elem* _String, size_type _Length, size_type _Pos, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_find(_String, _Length, _Pos, _XCS);
}

// Find in positive order from the specified location
XString::size_type XString::find(const XString& _String) const noexcept
{
	return this->_find(_String.data(), _String.size(), 0, Xanadu::CaseSensitive);
}

// Find in positive order from the specified location
XString::size_type XString::find(const XString& _String, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_find(_String.data(), _String.size(), 0, _XCS);
}

// Find in positive order from the specified location
XString::size_type XString::find(const XString& _String, size_type _Pos) const noexcept
{
	return this->_find(_String.data(), _String.size(), _Pos, Xanadu::CaseSensitive);
}

// Find in positive order from the specified location
XString::size_type XString::find(const XString& _String, size_type _Pos, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_find(_String.data(), _String.size(), _Pos, _XCS);
}



// Search in reverse order from the specified location
XString::size_type XString::rfind(_Elem _Char) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->_rfind(vBytes, 1, this->size() - 1, Xanadu::CaseSensitive);
}

// Search in reverse order from the specified location
XString::size_type XString::rfind(_Elem _Char, Xanadu::CaseSensitivity _XCS) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->_rfind(vBytes, 1, this->size() - 1, _XCS);
}

// Search in reverse order from the specified location
XString::size_type XString::rfind(_Elem _Char, size_type _Pos) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->_rfind(vBytes, 1, _Pos, Xanadu::CaseSensitive);
}

// Search in reverse order from the specified location
XString::size_type XString::rfind(_Elem _Char, size_type _Pos, Xanadu::CaseSensitivity _XCS) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->_rfind(vBytes, 1, _Pos, _XCS);
}

// Search in reverse order from the specified location
XString::size_type XString::rfind(const _Elem* _String) const noexcept
{
	return  this->_rfind(_String, Xanadu::strlen(_String), this->size() - 1, Xanadu::CaseSensitive);
}

// Search in reverse order from the specified location
XString::size_type XString::rfind(const _Elem* _String, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return  this->_rfind(_String, Xanadu::strlen(_String), this->size() - 1, _XCS);
}

// Search in reverse order from the specified location
XString::size_type XString::rfind(const _Elem* _String, size_type _Pos) const noexcept
{
	return  this->_rfind(_String, Xanadu::strlen(_String), _Pos, Xanadu::CaseSensitive);
}

// Search in reverse order from the specified location
XString::size_type XString::rfind(const _Elem* _String, size_type _Pos, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return  this->_rfind(_String, Xanadu::strlen(_String), _Pos, _XCS);
}

// Search in reverse order from the specified location
XString::size_type XString::rfind(const _Elem* _String, size_type _Length, size_type _Pos) const noexcept
{
	return this->_rfind(_String, _Length, _Pos, Xanadu::CaseSensitive);
}

// Search in reverse order from the specified location
XString::size_type XString::rfind(const _Elem* _String, size_type _Length, size_type _Pos, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_rfind(_String, _Length, _Pos, _XCS);
}

// Search in reverse order from the specified location
XString::size_type XString::rfind(const XString& _String) const noexcept
{
	return this->_rfind(_String.data(), _String.size(), this->size() - 1, Xanadu::CaseSensitive);
}

// Search in reverse order from the specified location
XString::size_type XString::rfind(const XString& _String, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_rfind(_String.data(), _String.size(), this->size() - 1, _XCS);
}

// Search in reverse order from the specified location
XString::size_type XString::rfind(const XString& _String, size_type _Pos) const noexcept
{
	return this->_rfind(_String.data(), _String.size(), _Pos, Xanadu::CaseSensitive);
}

// Search in reverse order from the specified location
XString::size_type XString::rfind(const XString& _String, size_type _Pos, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_rfind(_String.data(), _String.size(), _Pos, _XCS);
}



// Check whether the specified content is included
bool XString::contains(_Elem _Char) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->_contains(vBytes, 1, Xanadu::CaseSensitive);
}

// Check whether the specified content is included
bool XString::contains(_Elem _Char, Xanadu::CaseSensitivity _XCS) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->_contains(vBytes, 1, _XCS);
}

// Check whether the specified content is included
bool XString::contains(const _Elem* _String) const noexcept
{
	return this->_contains(_String, Xanadu::strlen(_String), Xanadu::CaseSensitive);
}

// Check whether the specified content is included
bool XString::contains(const _Elem* _String, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_contains(_String, Xanadu::strlen(_String), _XCS);
}

// Check whether the specified content is included
bool XString::contains(const _Elem* _String, size_type _Length) const noexcept
{
	return this->_contains(_String, _Length, Xanadu::CaseSensitive);
}

// Check whether the specified content is included
bool XString::contains(const _Elem* _String, size_type _Length, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_contains(_String, _Length, _XCS);
}

// Check whether the specified content is included
bool XString::contains(const XString& _String) const noexcept
{
	return this->_contains(_String.data(), _String.size(), Xanadu::CaseSensitive);
}

// Check whether the specified content is included
bool XString::contains(const XString& _String, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_contains(_String.data(), _String.size(), _XCS);
}



// Check that they are the same
int XString::compare(_Elem _Char) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->_compare(vBytes, 1, Xanadu::CaseSensitive);
}

// Check that they are the same
int XString::compare(_Elem _Char, Xanadu::CaseSensitivity _XCS) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->_compare(vBytes, 1, _XCS);
}

// Check that they are the same
int XString::compare(const _Elem* _String) const noexcept
{
	return this->_compare(_String, Xanadu::strlen(_String), Xanadu::CaseSensitive);
}

// Check that they are the same
int XString::compare(const _Elem* _String, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_compare(_String, Xanadu::strlen(_String), _XCS);
}

// Check that they are the same
int XString::compare(const _Elem* _String, size_type _Length) const noexcept
{
	return this->_compare(_String, _Length, Xanadu::CaseSensitive);
}

// Check that they are the same
int XString::compare(const _Elem* _String, size_type _Length, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_compare(_String, _Length, _XCS);
}

// Check that they are the same
int XString::compare(const XString& _String) const noexcept
{
	return this->_compare(_String.data(), _String.size(), Xanadu::CaseSensitive);
}

// Check that they are the same
int XString::compare(const XString& _String, Xanadu::CaseSensitivity _XCS) const noexcept
{
	return this->_compare(_String.data(), _String.size(), _XCS);
}



// Add at the begin
XString& XString::prepend(_Elem _Char) noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	this->_prepend(vBytes, 1);
	return *this;
}

// Add at the begin
XString& XString::prepend(const _Elem* _String) noexcept
{
	this->_prepend(_String, Xanadu::strlen(_String));
	return *this;
}

// Add at the begin
XString& XString::prepend(const _Elem* _String, size_type _Size) noexcept
{
	this->_prepend(_String, _Size);
	return *this;
}

// Add at the begin
XString& XString::prepend(const XString& _String) noexcept
{
	this->_prepend(_String.data(), _String.size());
	return *this;
}



// Add at the end
XString& XString::append(_Elem _Char) noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	this->_append(vBytes, 1);
	return *this;
}

// Add at the end
XString& XString::append(const _Elem* _String) noexcept
{
	this->_append(_String, Xanadu::strlen(_String));
	return *this;
}

// Add at the end
XString& XString::append(const _Elem* _String, size_type _Size) noexcept
{
	this->_append(_String, _Size);
	return *this;
}

// Add at the end
XString& XString::append(const XString& _String) noexcept
{
	this->_append(_String.data(), _String.size());
	return *this;
}



// Inserts data from the specified location _Elem
XString& XString::insert(size_type _Pos, _Elem _Char) noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	this->_insert(_Pos, vBytes, 1);
	return *this;
}

// Inserts data from the specified location _Elem
XString& XString::insert(size_type _Pos, size_type _Count, _Elem _Char) noexcept
{
	auto		vString = XString(_Count, _Char);
	this->_insert(_Pos, vString.data(), vString.size());
	return *this;
}

// Inserts data from the specified location const _Elem*
XString& XString::insert(size_type _Pos, const _Elem* _String) noexcept
{
	this->_insert(_Pos, _String, Xanadu::strlen(_String));
	return *this;
}

// Inserts data from the specified location const _Elem*
XString& XString::insert(size_type _Pos, const _Elem* _String, size_type _Length) noexcept
{
	this->_insert(_Pos, _String, _Length);
	return *this;
}

// Inserts data from the specified location XString
XString& XString::insert(size_type _Pos, const XString& _String) noexcept
{
	this->_insert(_Pos, _String.data(), _String.size());
	return *this;
}



// Removes the specified length of data from the specified location
XString& XString::remove(size_type _Pos, size_type _Length) noexcept
{
	this->_remove(_Pos, _Length);
	return *this;
}

// Delete the same data as the parameter
XString& XString::remove(_Elem _Char) noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	this->_remove(vBytes, 1, Xanadu::CaseSensitive);
	return *this;
}

// Delete the same data as the parameter
XString& XString::remove(_Elem _Char, Xanadu::CaseSensitivity _XCS) noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	this->_remove(vBytes, 1, _XCS);
	return *this;
}

// Delete the same data as the parameter
XString& XString::remove(const _Elem* _String) noexcept
{
	this->_remove(_String, Xanadu::strlen(_String), Xanadu::CaseSensitive);
	return *this;
}

// Delete the same data as the parameter
XString& XString::remove(const _Elem* _String, Xanadu::CaseSensitivity _XCS) noexcept
{
	this->_remove(_String, Xanadu::strlen(_String), _XCS);
	return *this;
}

// Delete the same data as the parameter
XString& XString::remove(const _Elem* _String, size_type _Length) noexcept
{
	this->_remove(_String, _Length, Xanadu::CaseSensitive);
	return *this;
}

// Delete the same data as the parameter
XString& XString::remove(const _Elem* _String, size_type _Length, Xanadu::CaseSensitivity _XCS) noexcept
{
	this->_remove(_String, _Length, _XCS);
	return *this;
}

// Delete the same data as the parameter
XString& XString::remove(const XString& _String) noexcept
{
	this->_remove(_String.data(), _String.size(), Xanadu::CaseSensitive);
	return *this;
}

// Delete the same data as the parameter
XString& XString::remove(const XString& _String, Xanadu::CaseSensitivity _XCS) noexcept
{
	this->_remove(_String.data(), _String.size(), _XCS);
	return *this;
}



// Replace the specified data
XString& XString::replace(size_type _Pos, size_type _Length, _Elem _After) noexcept
{
	_Elem		vAfter[2] = { _After, '\0' };
	this->_replace(_Pos, _Length, vAfter, 1);
	return *this;
}

// Replace the specified data
XString& XString::replace(size_type _Pos, size_type _Length, const _Elem* _After) noexcept
{
	this->_replace(_Pos, _Length, _After, Xanadu::strlen(_After));
	return *this;
}

// Replace the specified data
XString& XString::replace(size_type _Pos, size_type _Length, const _Elem* _After, size_type _LengthA) noexcept
{
	this->_replace(_Pos, _Length, _After, _LengthA);
	return *this;
}

// Replace the specified data
XString& XString::replace(size_type _Pos, size_type _Length, const XString& _After) noexcept
{
	this->_replace(_Pos, _Length, _After.data(), _After.size());
	return *this;
}



// Replace the specified data
XString& XString::replace(_Elem _Before, _Elem _After) noexcept
{
	_Elem		vBefore[2] = { _Before, '\0' };
	_Elem		vAfter[2] = { _After, '\0' };
	this->_replace(vBefore, 1, vAfter, 1, Xanadu::CaseSensitive);
	return *this;
}

// Replace the specified data
XString& XString::replace(_Elem _Before, _Elem _After, Xanadu::CaseSensitivity _XCS) noexcept
{
	_Elem		vBefore[2] = { _Before, '\0' };
	_Elem		vAfter[2] = { _After, '\0' };
	this->_replace(vBefore, 1, vAfter, 1, _XCS);
	return *this;
}

// Replace the specified data
XString& XString::replace(_Elem _Before, const _Elem* _After, size_type _LengthA) noexcept
{
	_Elem		vBefore[2] = { _Before, '\0' };
	this->_replace(vBefore, 1, _After, _LengthA, Xanadu::CaseSensitive);
	return *this;
}

// Replace the specified data
XString& XString::replace(_Elem _Before, const _Elem* _After, size_type _LengthA, Xanadu::CaseSensitivity _XCS) noexcept
{
	_Elem		vBefore[2] = { _Before, '\0' };
	this->_replace(vBefore, 1, _After, _LengthA, _XCS);
	return *this;
}

// Replace the specified data
XString& XString::replace(_Elem _Before, const XString& _After) noexcept
{
	_Elem		vBefore[2] = { _Before, '\0' };
	this->_replace(vBefore, 1, _After.data(), _After.size(), Xanadu::CaseSensitive);
	return *this;
}

// Replace the specified data
XString& XString::replace(_Elem _Before, const XString& _After, Xanadu::CaseSensitivity _XCS) noexcept
{
	_Elem		vBefore[2] = { _Before, '\0' };
	this->_replace(vBefore, 1, _After.data(), _After.size(), _XCS);
	return *this;
}



// Replace the specified data
XString& XString::replace(const _Elem* _Before, _Elem _After) noexcept
{
	_Elem		vAfter[2] = { _After, '\0' };
	this->_replace(_Before, Xanadu::strlen(_Before), vAfter, 1, Xanadu::CaseSensitive);
	return *this;
}

// Replace the specified data
XString& XString::replace(const _Elem* _Before, _Elem _After, Xanadu::CaseSensitivity _XCS) noexcept
{
	_Elem		vAfter[2] = { _After, '\0' };
	this->_replace(_Before, Xanadu::strlen(_Before), vAfter, 1, _XCS);
	return *this;
}

// Replace the specified data
XString& XString::replace(const _Elem* _Before, const _Elem* _After, size_type _LengthA) noexcept
{
	this->_replace(_Before, Xanadu::strlen(_Before), _After, _LengthA, Xanadu::CaseSensitive);
	return *this;
}

// Replace the specified data
XString& XString::replace(const _Elem* _Before, const _Elem* _After, size_type _LengthA, Xanadu::CaseSensitivity _XCS) noexcept
{
	this->_replace(_Before, Xanadu::strlen(_Before), _After, _LengthA, _XCS);
	return *this;
}

// Replace the specified data
XString& XString::replace(const _Elem* _Before, const XString& _After) noexcept
{
	this->_replace(_Before, Xanadu::strlen(_Before), _After.data(), _After.size(), Xanadu::CaseSensitive);
	return *this;
}

// Replace the specified data
XString& XString::replace(const _Elem* _Before, const XString& _After, Xanadu::CaseSensitivity _XCS) noexcept
{
	this->_replace(_Before, Xanadu::strlen(_Before), _After.data(), _After.size(), _XCS);
	return *this;
}



// Replace the specified data
XString& XString::replace(const _Elem* _Before, size_type _LengthB, _Elem _After) noexcept
{
	_Elem		vAfter[2] = { _After, '\0' };
	this->_replace(_Before, _LengthB, vAfter, 1, Xanadu::CaseSensitive);
	return *this;
}

// Replace the specified data
XString& XString::replace(const _Elem* _Before, size_type _LengthB, _Elem _After, Xanadu::CaseSensitivity _XCS) noexcept
{
	_Elem		vAfter[2] = { _After, '\0' };
	this->_replace(_Before, _LengthB, vAfter, 1, _XCS);
	return *this;
}

// Replace the specified data
XString& XString::replace(const _Elem* _Before, size_type _LengthB, const _Elem* _After, size_type _LengthA) noexcept
{
	this->_replace(_Before, _LengthB, _After, _LengthA, Xanadu::CaseSensitive);
	return *this;
}

// Replace the specified data
XString& XString::replace(const _Elem* _Before, size_type _LengthB, const _Elem* _After, size_type _LengthA, Xanadu::CaseSensitivity _XCS) noexcept
{
	this->_replace(_Before, _LengthB, _After, _LengthA, _XCS);
	return *this;
}

// Replace the specified data
XString& XString::replace(const _Elem* _Before, size_type _LengthB, const XString& _After) noexcept
{
	this->_replace(_Before, _LengthB, _After.data(), _After.size(), Xanadu::CaseSensitive);
	return *this;
}

// Replace the specified data
XString& XString::replace(const _Elem* _Before, size_type _LengthB, const XString& _After, Xanadu::CaseSensitivity _XCS) noexcept
{
	this->_replace(_Before, _LengthB, _After.data(), _After.size(), _XCS);
	return *this;
}



// Replace the specified data
XString& XString::replace(const XString& _Before, _Elem _After) noexcept
{
	_Elem		vAfter[2] = { _After, '\0' };
	this->_replace(_Before.data(), _Before.size(), vAfter, 1, Xanadu::CaseSensitive);
	return *this;
}

// Replace the specified data
XString& XString::replace(const XString& _Before, _Elem _After, Xanadu::CaseSensitivity _XCS) noexcept
{
	_Elem		vAfter[2] = { _After, '\0' };
	this->_replace(_Before.data(), _Before.size(), vAfter, 1, _XCS);
	return *this;
}

// Replace the specified data
XString& XString::replace(const XString& _Before, const _Elem* _After, size_type _LengthA) noexcept
{
	this->_replace(_Before.data(), _Before.size(), _After, _LengthA, Xanadu::CaseSensitive);
	return *this;
}

// Replace the specified data
XString& XString::replace(const XString& _Before, const _Elem* _After, size_type _LengthA, Xanadu::CaseSensitivity _XCS) noexcept
{
	this->_replace(_Before.data(), _Before.size(), _After, _LengthA, _XCS);
	return *this;
}

// Replace the specified data
XString& XString::replace(const XString& _Before, const XString& _After) noexcept
{
	this->_replace(_Before.data(), _Before.size(), _After.data(), _After.size(), Xanadu::CaseSensitive);
	return *this;
}

// Replace the specified data
XString& XString::replace(const XString& _Before, const XString& _After, Xanadu::CaseSensitivity _XCS) noexcept
{
	this->_replace(_Before.data(), _Before.size(), _After.data(), _After.size(), _XCS);
	return *this;
}



// Splits an array by the specified data
std::list<XString> XString::split(_Elem _Char) const noexcept
{
	_Elem		vBytes[2] = { _Char, '\0' };
	return this->split(vBytes, 1);
}

// Splits an array by the specified data
std::list<XString> XString::split(const _Elem* _Memory) const noexcept
{
	return this->split(XString(_Memory));
}

// Splits an array by the specified data
std::list<XString> XString::split(const _Elem* _Memory, size_type _Size) const noexcept
{
	return this->split(XString(_Memory, _Size));
}

// Splits an array by the specified data
std::list<XString> XString::split(const XString& _Bytes) const noexcept
{
	auto		vHeaderArray = std::list<XString>();
	auto		vLast = static_cast<size_type>(0U);
	auto		vSplitIndex = this->find(_Bytes, vLast);
	while(vSplitIndex != XString::npos && _Bytes.exist())
	{
		vHeaderArray.push_back(this->mid(vLast, vSplitIndex - vLast));
		vLast = vSplitIndex + 2;
		vSplitIndex = this->find(_Bytes, vLast);
	}
	vHeaderArray.push_back(this->mid(vLast));

	return vHeaderArray;
}



// Determine whether a character is a blank character, Same as iswspace.
bool XString::isSpace(_Elem _Char) noexcept
{
	// Non-zero value if the wide character is a whitespace character, zero otherwise.
	return Xanadu::isspace(_Char);
}

// Format string (char* [%s]) (wchar_t* [%ls])
XString XString::format(const char* _Format, ...) noexcept
{
	auto		vString = XString();
	va_list		vArgs1;
	va_list		vArgs2;
	va_start(vArgs1, _Format);
	va_copy(vArgs2, vArgs1);
	auto		vSize = std::vsnprintf(nullptr, 0, _Format, vArgs1);
	if(vSize > 0)
	{
		vString.resize(vSize + 1);
		std::vsnprintf(vString.data(), vString.size(), _Format, vArgs2);
		vString.remove(vSize, 1);
	}
	va_end(vArgs1);
	va_end(vArgs2);
	return vString;
}



// [convert] convert to uppercase
XString XString::toUpper() const noexcept
{
	auto		vTemp = *this;
	for(auto vIndex = 0U; vIndex < this->size(); ++vIndex)
	{
		vTemp[vIndex] = (XString::_Elem)std::toupper(vTemp[vIndex]);
	}
	return vTemp;
}

// [convert] convert to lowercase
XString XString::toLower() const noexcept
{
	auto		vTemp = *this;
	for(auto vIndex = 0U; vIndex < this->size(); ++vIndex)
	{
		vTemp[vIndex] = (XString::_Elem)std::tolower(vTemp[vIndex]);
	}
	return vTemp;
}



// [convert] convert to base64
XString XString::toBase64() const noexcept
{
	auto		vBytes = XBase64::encode(this->data(), this->size());
	return {vBytes.data(), vBytes.size()};
}

// [convert] convert from base64
XString XString::fromBase64(const _Elem* _String, size_type _Size) noexcept
{
	auto		vBytes = XBase64::decode(_String, _Size);
	return {vBytes.data(), vBytes.size()};
}

// [convert] convert from base64
XString XString::fromBase64(const XString& _Base64) noexcept
{
	return XString::fromBase64(_Base64.data(), _Base64.size());
}



// [convert] convert to Hex
XString XString::toHex() const noexcept
{
	auto		vTarget = XString(this->size() * 2, '0');
	for (auto vIndex = 0U; vIndex < this->size(); ++vIndex)
	{
		sprintf(vTarget.data() + (vIndex * 2), "%02X", (std::uint8_t)this->data()[vIndex]);
	}
	return vTarget;
}

// [convert] convert from Hex
XString XString::fromHex(const _Elem* _String, size_type _Size) noexcept
{
	if (nullptr == _String)
	{
		return XString();
	}
	if(_Size == XString::npos)
	{
		_Size = Xanadu::strlen(static_cast<const char*>(_String));
	}
	auto		vFunctionHexToChar = [](char _Char)
		{
			if ((_Char >= 'A') && (_Char <= 'Z'))
			{
				return _Char - 'A' + 10;
			}
			else if ((_Char >= 'a') && (_Char <= 'z'))
			{
				return _Char - 'a' + 10;
			}
			else if ((_Char >= '0') && (_Char <= '9'))
			{
				return _Char - '0';
			}
			return 0;
		};
	auto		vBuffer = static_cast<const char*>(_String);
	auto		vLength = _Size / 2;
	auto		vTarget = XString(vLength, '\0');
	if(_Size > 0ULL)
	{
		for (auto vIndex = 0U; vIndex < vLength; ++vIndex)
		{
			auto		vHexLeft = vFunctionHexToChar(vBuffer[vIndex * 2 + 0]);
			auto		vHexRight = vFunctionHexToChar(vBuffer[vIndex * 2 + 1]);
			vTarget[vIndex] = static_cast<char>(vHexLeft * 16 + vHexRight);
		}
	}
	return vTarget;
}

// [convert] convert from Hex
XString XString::fromHex(const XString& _Hex) noexcept
{
	return XString::fromHex(_Hex.data(), _Hex.size());
}



// [convert] convert to ASCII encoded string
AString XString::toAString() const noexcept
{
	auto		vWString = this->toWString();
	auto		vAString = AString();
	auto		vChangeStr = Xanadu::strwtoa(vWString.data());
	if(vChangeStr)
	{
		vAString = vChangeStr;
		Xanadu::strfree(vChangeStr);
	}
	return vAString;
}

// [convert] convert from ASCII encoded string
XString XString::fromAString(const char* _AString) noexcept
{
	auto		vXString = WString();
	auto		vChangeStr = Xanadu::stratow(_AString);
	if(vChangeStr)
	{
		vXString = vChangeStr;
		Xanadu::wcsfree(vChangeStr);
	}
	return XString::fromWString(vXString);
}

// [convert] convert from ASCII encoded string
XString XString::fromAString(const AString& _AString) noexcept
{
	return XString::fromAString(_AString.data());
}



// [convert] convert to UNICODE encoded string
WString XString::toWString() const noexcept
{
	auto		vXString = WString();
	auto		vChangeStr = Xanadu::strutow(this->data());
	if(vChangeStr)
	{
		vXString = vChangeStr;
		Xanadu::wcsfree(vChangeStr);
	}
	return vXString;
}

// [convert] convert from UNICODE
XString XString::fromWString(const wchar_t* _WString) noexcept
{
	auto		vUString = XString();
	auto		vChangeStr = Xanadu::strwtou(_WString);
	if(vChangeStr)
	{
		vUString = vChangeStr;
		Xanadu::strfree(vChangeStr);
	}
	return vUString;
}

// [convert] convert from UNICODE
XString XString::fromWString(const WString& _WString) noexcept
{
	return XString::fromWString(_WString.data());
}



// [convert] convert to UTF-8 encoded string
UString XString::toUString() const noexcept
{
	return UString(this->data(), this->size());
}

// [convert] convert from UTF-8
XString XString::fromUString(const char* _UString) noexcept
{
	return XString(_UString);
}

// [convert] convert from UTF-8
XString XString::fromUString(const UString& _UString) noexcept
{
	return XString(_UString);
}



// [convert] convert to native (Windows: ASCII / other: UTF-8) encoded string
NString XString::toNString() const noexcept
{
#if defined(_XANADU_SYSTEM_WINDOWS)
	return this->toAString();
#else
	return this->toUString();
#endif
}

// [convert] convert from native (Windows: ASCII / other: UTF-8)
XString XString::fromNString(const char* _NString) noexcept
{
#if defined(_XANADU_SYSTEM_WINDOWS)
	return XString::fromAString(_NString);
#else
	return XString::fromUString(_NString);
#endif
}

// [convert] convert from native (Windows: ASCII / other: UTF-8)
XString XString::fromNString(const NString& _NString) noexcept
{
	return XString::fromNString(_NString.data());
}



// [convert] convert to UTF-8 encoded byte array
XByteArray XString::toBytes() const noexcept
{
	return XByteArray(this->data(), this->size());
}

// [convert] convert from byte array
XString XString::fromBytes(const XByteArray& _Bytes) noexcept
{
	return XString(_Bytes.data(), _Bytes.size());
}



// [convert] convert to UTF-8 encoded url
XString XString::toUrl() const noexcept
{
	auto		vDecode = toUString();
	auto		vEncode = UString();
	for(char vChar : vDecode)
	{
		if(((vChar >= 'A') && (vChar <= 'Z')) || ((vChar >= 'a') && (vChar <= 'z')) || ((vChar >= '0') && (vChar <= '9')))
		{
			vEncode.append(1, vChar);
		}
		else if(vChar == ' ')
		{
			vEncode.append("%20");
		}
		else if(vChar == '.' || vChar == '-' || vChar == '_' || vChar == '*' || vChar == ':' || vChar == '/' || vChar == ',')
		{
			vEncode.append(1, vChar);
		}
		else if(vChar == '&' || vChar == '?' || vChar == '=')
		{
			vEncode.append(1, vChar);
		}
		else
		{
			char	_Buffer[16] = { 0 };
			sprintf(_Buffer, "%%%02X", (unsigned char)vChar);
			vEncode.append(_Buffer);
		}
	}
	return vEncode;
}

// [convert] convert from UTF-8 encoded url
XString XString::fromUrl(const XString& _URL) noexcept
{
	auto		vEncode = _URL.toUString();
	auto		vDecode = UString();

	auto		Function_Hex2Num = [](char _Char)->int
	{
		if(_Char >= '0' && _Char <= '9')
		{
			return _Char - '0';
		}
		if(_Char >= 'a' && _Char <= 'z')
		{
			return _Char - 'a' + 10;
		}
		if(_Char >= 'A' && _Char <= 'Z')
		{
			return _Char - 'A' + 10;
		}
		return '0';
	};

	for(auto vIterator = vEncode.begin(); vIterator != vEncode.end(); ++vIterator)
	{
		auto	_Char = (*vIterator);
		switch(_Char)
		{
			case '%':
				if((vIterator + 2) != vEncode.end())
				{
					auto	_Char1 = Function_Hex2Num(*(vIterator + 1));
					auto	_Char2 = Function_Hex2Num(*(vIterator + 2));
					if((_Char1 != '0') && (_Char2 != '0'))
					{
						vDecode.append(1, (char)((_Char1 << 4) | _Char2));
					}
					vIterator += 2;
				}
				break;
			default:
				vDecode.append(1, _Char);
				break;
		}
	}
	return fromUString(vDecode);
}



// [convert] convert to char
char XString::toChar(bool* _Ok, int _Base) const noexcept
{
	return static_cast<char>(this->toLLong(_Ok, _Base));
}

// [convert] convert to unsigned char
unsigned char XString::toUChar(bool* _Ok, int _Base) const noexcept
{
	return static_cast<unsigned char>(this->toULLong(_Ok, _Base));
}

// [convert] convert to short
short XString::toShort(bool* _Ok, int _Base) const noexcept
{
	return static_cast<short>(this->toLLong(_Ok, _Base));
}

// [convert] convert to short
unsigned short XString::toUShort(bool* _Ok, int _Base) const noexcept
{
	return static_cast<unsigned short>(this->toULLong(_Ok, _Base));
}

// [convert] convert to int
int XString::toInt(bool* _Ok, int _Base) const noexcept
{
	return static_cast<int>(this->toLLong(_Ok, _Base));
}

// [convert] convert to unsigned int
unsigned int XString::toUInt(bool* _Ok, int _Base) const noexcept
{
	return static_cast<unsigned int>(this->toULLong(_Ok, _Base));
}

// [convert] convert to long
long XString::toLong(bool* _Ok, int _Base) const noexcept
{
	return static_cast<long>(this->toLLong(_Ok, _Base));
}

// [convert] convert to unsigned long
unsigned long XString::toULong(bool* _Ok, int _Base) const noexcept
{
	return static_cast<unsigned long>(this->toULLong(_Ok, _Base));
}

// [convert] convert to long long
long long XString::toLLong(bool* _Ok, int _Base) const noexcept
{
	auto		vEnd = static_cast<_Elem*>(nullptr);
	auto		vValue = std::strtoll(this->data(), &vEnd, _Base);

	if(_Ok)
	{
		if(vEnd && vEnd[0] == '\0')
		{
			*_Ok = true;
		}
		else
		{
			*_Ok = false;
		}
	}

	return vValue;
}

// [convert] convert to unsigned long long
unsigned long long XString::toULLong(bool* _Ok, int _Base) const noexcept
{
	auto		vEnd = static_cast<_Elem*>(nullptr);
	auto		vValue = std::strtoull(this->data(), &vEnd, _Base);

	if(_Ok)
	{
		if(vEnd && vEnd[0] == '\0')
		{
			*_Ok = true;
		}
		else
		{
			*_Ok = false;
		}
	}

	return vValue;
}

// [convert] convert to float
float XString::toFloat(bool* _Ok) const noexcept
{
	auto		vEnd = static_cast<_Elem*>(nullptr);
	auto		vValue = std::strtof(this->data(), &vEnd);

	if(_Ok)
	{
		if(vEnd && vEnd[0] == '\0')
		{
			*_Ok = true;
		}
		else
		{
			*_Ok = false;
		}
	}

	return vValue;
}

// [convert] convert to double
double XString::toDouble(bool* _Ok) const noexcept
{
	auto		vEnd = static_cast<_Elem*>(nullptr);
	auto		vValue = std::strtod(this->data(), &vEnd);

	if(_Ok)
	{
		if(vEnd && vEnd[0] == '\0')
		{
			*_Ok = true;
		}
		else
		{
			*_Ok = false;
		}
	}

	return vValue;
}



// [convert] convert from number
XString& XString::setNumber(char _Value, int _Base) noexcept
{
	this->setNumber(static_cast<long long>(_Value), _Base);
	return *this;
}

// [convert] convert from number
XString& XString::setNumber(unsigned char _Value, int _Base) noexcept
{
	this->setNumber(static_cast<unsigned long long>(_Value), _Base);
	return *this;
}

// [convert] convert from number
XString& XString::setNumber(short _Value, int _Base) noexcept
{
	this->setNumber(static_cast<long long>(_Value), _Base);
	return *this;
}

// [convert] convert from number
XString& XString::setNumber(unsigned short _Value, int _Base) noexcept
{
	this->setNumber(static_cast<unsigned long long>(_Value), _Base);
	return *this;
}

// [convert] convert from number
XString& XString::setNumber(int _Value, int _Base) noexcept
{
	this->setNumber(static_cast<long long>(_Value), _Base);
	return *this;
}

// [convert] convert from number
XString& XString::setNumber(unsigned int _Value, int _Base) noexcept
{
	this->setNumber(static_cast<unsigned long long>(_Value), _Base);
	return *this;
}

// [convert] convert from number
XString& XString::setNumber(long _Value, int _Base) noexcept
{
	this->setNumber(static_cast<long long>(_Value), _Base);
	return *this;
}

// [convert] convert from number
XString& XString::setNumber(unsigned long _Value, int _Base) noexcept
{
	this->setNumber(static_cast<unsigned long long>(_Value), _Base);
	return *this;
}

// [convert] convert from number
XString& XString::setNumber(long long _Value, int _Base) noexcept
{
	if(2 <= _Base && _Base <= 36)
	{
		*this = std::to_string(_Value).data();
	}
	return *this;
}

// [convert] convert from number
XString& XString::setNumber(unsigned long long _Value, int _Base) noexcept
{
	if(2 <= _Base && _Base <= 36)
	{
		*this = std::to_string(_Value).data();
	}
	return *this;
}

// [convert] convert from number
XString& XString::setNumber(float _Value, char _Format, int _Prec) noexcept
{
	XANADU_UNPARAMETER(_Format);
	XANADU_UNPARAMETER(_Prec);

	*this = std::to_string(_Value).data();
	return *this;
}

// [convert] convert from number
XString& XString::setNumber(double _Value, char _Format, int _Prec) noexcept
{
	XANADU_UNPARAMETER(_Format);
	XANADU_UNPARAMETER(_Prec);

	*this = std::to_string(_Value).data();
	return *this;
}



// [convert] convert from number
XString XString::number(char _Value, int _Base) noexcept
{
	auto		vValue = XString();
	vValue.setNumber(_Value, _Base);
	return vValue;
}

// [convert] convert from number
XString XString::number(unsigned char _Value, int _Base) noexcept
{
	auto		vValue = XString();
	vValue.setNumber(_Value, _Base);
	return vValue;
}

// [convert] convert from number
XString XString::number(short _Value, int _Base) noexcept
{
	auto		vValue = XString();
	vValue.setNumber(_Value, _Base);
	return vValue;
}

// [convert] convert from number
XString XString::number(unsigned short _Value, int _Base) noexcept
{
	auto		vValue = XString();
	vValue.setNumber(_Value, _Base);
	return vValue;
}

// [convert] convert from number
XString XString::number(int _Value, int _Base) noexcept
{
	auto		vValue = XString();
	vValue.setNumber(_Value, _Base);
	return vValue;
}

// [convert] convert from number
XString XString::number(unsigned int _Value, int _Base) noexcept
{
	auto		vValue = XString();
	vValue.setNumber(_Value, _Base);
	return vValue;
}

// [convert] convert from number
XString XString::number(long _Value, int _Base) noexcept
{
	auto		vValue = XString();
	vValue.setNumber(_Value, _Base);
	return vValue;
}

// [convert] convert from number
XString XString::number(unsigned long _Value, int _Base) noexcept
{
	auto		vValue = XString();
	vValue.setNumber(_Value, _Base);
	return vValue;
}

// [convert] convert from number
XString XString::number(long long _Value, int _Base) noexcept
{
	auto		vValue = XString();
	vValue.setNumber(_Value, _Base);
	return vValue;
}

// [convert] convert from number
XString XString::number(unsigned long long _Value, int _Base) noexcept
{
	auto		vValue = XString();
	vValue.setNumber(_Value, _Base);
	return vValue;
}

// [convert] convert from number
XString XString::number(float _Value, char _Format, int _Prec) noexcept
{
	auto		vValue = XString();
	vValue.setNumber(_Value, _Format, _Prec);
	return vValue;
}

// [convert] convert from number
XString XString::number(double _Value, char _Format, int _Prec) noexcept
{
	auto		vValue = XString();
	vValue.setNumber(_Value, _Format, _Prec);
	return vValue;
}



// Standard enhancement function : stream <<
XANADU_CORE_EXPORT std::ostream& operator<< (std::ostream& _OStream, const XString& _String) noexcept
{
	for(auto vIndex = 0U; vIndex < _String.length(); ++vIndex)
	{
		_OStream << _String[vIndex];
	}
	return _OStream;
}

// Standard enhancement function : stream >>
XANADU_CORE_EXPORT std::istream& operator>> (std::istream& _IStream, XString& _String) noexcept
{
	_String.clear();
	do
	{
		auto		vChar = static_cast<XString::_Elem>(_IStream.get());
		if(vChar == '\n' || vChar == ' ')
		{
			break;
		}
		_String.append(vChar);
	} while(true);
	return _IStream;
}

// Standard enhancement function : getline
XANADU_CORE_EXPORT std::istream& getline(std::istream& _IStream, XString& _String, char _Delim) noexcept
{
	_String.clear();
	do
	{
		auto		vChar = static_cast<XString::_Elem>(_IStream.get());
		if(vChar == _Delim)
		{
			break;
		}
		_String.append(vChar);
	} while(true);
	return _IStream;
}

// Standard enhancement function : getline
XANADU_CORE_EXPORT std::istream& getline(std::istream& _IStream, XString& _String) noexcept
{
	return getline(_IStream, _String, '\n');
}

